package org.totoro.amap.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.totoro.amap.config.Key;
import org.totoro.amap.enums.Level;
import org.totoro.amap.repo.PoiCityInfoRepo;
import org.totoro.amap.repo.entity.PoiCityInfoEntity;
import org.totoro.amap.repo.entity.QPoiCityInfoEntity;
import org.totoro.amap.repo.entity.QPoiCityInfoPolylineEntity;
import org.totoro.amap.response.DistrictsResponse;
import org.totoro.amap.service.PoiCityInfoService;
import org.totoro.amap.service.bo.PoiCityInfoBo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 国家城市服务 实现
 *
 * @author yhl
 */
@Service
@Slf4j
public class PoiCityInfoServiceImpl implements PoiCityInfoService {

    @Autowired
    private PoiCityInfoRepo countryRepo;

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Override
    public PoiCityInfoBo save(PoiCityInfoBo countryBo) {

        PoiCityInfoEntity countryTableEntity = getCountryTableEntity(countryBo);

        PoiCityInfoEntity save = countryRepo.save(countryTableEntity);

        PoiCityInfoBo countryBo1 = getCountryBo(save);

        return countryBo1;
    }

    public List<PoiCityInfoBo> saveAll(List<PoiCityInfoBo> countryBos) {

        List<PoiCityInfoEntity> collect = countryBos.stream().map(this::getCountryTableEntity).collect(Collectors.toList());

        List<PoiCityInfoEntity> result = countryRepo.saveAll(collect);

        List<PoiCityInfoBo> collect1 = result.stream().map(this::getCountryBo).collect(Collectors.toList());

        return collect1;

    }

    @Override
    public List<PoiCityInfoBo> findCountryBoByLevel(Level level) {

        QPoiCityInfoEntity countryTableEntity = QPoiCityInfoEntity.poiCityInfoEntity;

        List<PoiCityInfoEntity> fetch = jpaQueryFactory.selectFrom(countryTableEntity)
                .where(countryTableEntity.level.eq(level.name())).fetch();

        List<PoiCityInfoBo> collect = fetch.stream().map(this::getCountryBo).collect(Collectors.toList());

        return collect;
    }

    @Override
    public List<PoiCityInfoBo> findNotFindPolylineCountryBo(Level level) {

        QPoiCityInfoEntity countryTableEntity = QPoiCityInfoEntity.poiCityInfoEntity;

        QPoiCityInfoPolylineEntity countryPolylineEntity = QPoiCityInfoPolylineEntity.poiCityInfoPolylineEntity;

        List<PoiCityInfoEntity> fetch = jpaQueryFactory.select(countryTableEntity).from(countryTableEntity).leftJoin(countryPolylineEntity)
                .on(countryTableEntity.adcCode.eq(countryPolylineEntity.adcCode))
                .where(countryTableEntity.level.eq(level.name()), countryPolylineEntity.id.isNull()).fetch();

        List<PoiCityInfoBo> collect = fetch.stream().map(this::getCountryBo).collect(Collectors.toList());

        return collect;
    }

    private PoiCityInfoBo getCountryBo(PoiCityInfoEntity save) {
        PoiCityInfoBo countryBo1 = new PoiCityInfoBo();
        BeanUtils.copyProperties(save, countryBo1);
        return countryBo1;
    }

    private PoiCityInfoEntity getCountryTableEntity(PoiCityInfoBo countryBo) {
        PoiCityInfoEntity countryTableEntity = new PoiCityInfoEntity();
        BeanUtils.copyProperties(countryBo, countryTableEntity);
        return countryTableEntity;
    }

    @Override
    public void loadCity() {

        String url = "restapi.amap.com/v3/config/district?key=" + Key.loadbalancing() + "&keywords=中国&subdistrict=3&extensions=base";

        HttpResponse execute = HttpUtil.createGet(url).execute();

        DistrictsResponse districtsResponse = JSONUtil.toBean(execute.body(), DistrictsResponse.class);

        saveCity(districtsResponse.getDistricts(), null);
    }

    @Override
    public void loadStreet() {

        List<PoiCityInfoBo> countryBoByLevel = this.findCountryBoByLevel(Level.district);

        for (PoiCityInfoBo countryBo : countryBoByLevel) {

            String url = "restapi.amap.com/v3/config/district?key=" + Key.loadbalancing() + "&keywords=" + countryBo.getAdcName() + "&subdistrict=3&extensions=base";

            HttpResponse execute = HttpUtil.createGet(url).execute();

            DistrictsResponse districtsResponse = JSONUtil.toBean(execute.body(), DistrictsResponse.class);

            List<DistrictsResponse.DistrictsVO> districts = districtsResponse.getDistricts();

            for (DistrictsResponse.DistrictsVO district : districts) {
                saveStreet(district);
            }
        }

    }

    private void saveCity(List<DistrictsResponse.DistrictsVO> districtsVOXXXES, String parentCode) {

        if (ObjectUtils.isEmpty(districtsVOXXXES)) {
            return;
        }

        for (DistrictsResponse.DistrictsVO districtsVOXXX : districtsVOXXXES) {

            PoiCityInfoBo countryBo = new PoiCityInfoBo();
            countryBo.setAdcCode(districtsVOXXX.getAdcode());
            countryBo.setCityCode(districtsVOXXX.getCitycode());
            countryBo.setAdcName(districtsVOXXX.getName());
            countryBo.setLevel(districtsVOXXX.getLevel());
            countryBo.setParentAdcCode(parentCode);
            String center = districtsVOXXX.getCenter();
            String[] split = center.split(",");
            countryBo.setLongitude(split[0]);
            countryBo.setLatitude(split[1]);
            countryBo.setCreateTime(new Date());
            countryBo.setUpdateTime(new Date());

            save(countryBo);

            saveCity(districtsVOXXX.getDistricts(), districtsVOXXX.getAdcode());
        }
    }


    private void saveStreet(DistrictsResponse.DistrictsVO districtsVOXXXES) {

        if (ObjectUtils.isEmpty(districtsVOXXXES)) {
            return;
        }

        if (!Level.district.name().equals(districtsVOXXXES.getLevel())) {

            List<DistrictsResponse.DistrictsVO> districts = districtsVOXXXES.getDistricts();

            for (DistrictsResponse.DistrictsVO district : districts) {
                saveStreet(district);
            }

            return;
        }

        if (Level.district.name().equals(districtsVOXXXES.getLevel())) {

            ArrayList<PoiCityInfoBo> countryBos = new ArrayList<>();

            Integer index = 0;
            for (DistrictsResponse.DistrictsVO districtsVOXXX : districtsVOXXXES.getDistricts()) {

                PoiCityInfoBo countryBo = new PoiCityInfoBo();

                countryBo.setAdcCode(districtsVOXXX.getAdcode() + "00" + districtsVOXXXES.getCitycode() + (++index));
                countryBo.setCityCode(districtsVOXXX.getCitycode());
                countryBo.setAdcName(districtsVOXXX.getName());
                countryBo.setLevel(districtsVOXXX.getLevel());
                countryBo.setParentAdcCode(districtsVOXXXES.getAdcode());
                String center = districtsVOXXX.getCenter();
                String[] split = center.split(",");
                countryBo.setLongitude(split[0]);
                countryBo.setLatitude(split[1]);
                countryBo.setCreateTime(new Date());
                countryBo.setUpdateTime(new Date());
                countryBos.add(countryBo);
            }

            this.saveAll(countryBos);

        }
    }

    @Override
    public void loadPlate() throws IOException, InterruptedException {


    }

}
